<?php
namespace Core\Libs\ClassLoader;

class ClassLoader extends \Core\Libs\Registry\RegistryNamespace {

	//public static $new;
	private static $resetProperties = TRUE;
	private static $_classSingleton = NULL;

	final public function &params() {

		self::$_arrayParams =& func_get_args();
		return $this;
	}

	final public function &setClassSingleton($bool = TRUE) {

		self::$_classSingleton =& $bool;
		return $this;
	}

	final public function &setResetProperties($bool = TRUE) {

		self::$resetProperties =& $bool;
		return $this;
	}

	final public function &getClassSingleton() {

		return self::$_classSingleton;
	}

	final public function &getResetProperties() {

		return self::$resetProperties;
	}

	final public static function getClass($path) {

		return self::getInstance(&$path);
	}

	final public static function getObject($path) {

		return self::getInstance(&$path);
	}

	final public static function &getInstance($path) {

		//self::$_newClasseAtivo = TRUE;
		$totalParams = 0;
		$caminho = NULL;
		$auxCaminho = NULL;
		$nameSpace = NULL;
		$idClasse = NULL;
		$carregarNameSpace = NULL;

		extract(self::_processStringJabezInc(&$path, 'object', NULL, 'class', TRUE, 'array'), EXTR_REFS & EXTR_OVERWRITE);

		if($totalParams > 1) {

			try {

				if(empty(self::$_arrayInstancias[$idClasse]) || !is_object(self::$_arrayInstancias[$idClasse])) {

					 parent::includeFilesRecursively($caminho, $nameSpace, TRUE);
				}
			}

			catch(\Exception $e) {

				if(empty($auxCaminho)) {

					$auxCaminho = $caminho;
				}

				if(!strpos(&$carregarNameSpace, T_NS_SEPARATOR)) {

					$carregarNameSpace = 'Namespace em formato inválido.';
				}

				throw \Core\Uses\Exception('Falha ao incluir o arquivo: '.$auxCaminho.'<br>'.'Namespace não incluído e não carregado: '.$carregarNameSpace.'<br>'.'Erro interno do php: '.$e->getMessage());
			}
		}

		$clsSing = self::$_arrayInstances[$idClasse]['properties']['classeSingleton'];
		$totalParams =& count(&self::$_arrayParams);

		if($clsSing === NULL) {

			$clsSing = self::$_classSingleton;

			if($clsSing === NULL) {

				$clsSing = self::$classeSingleton;
			}
		}

		$init =& self::loadInstance(array(&$nameSpace, &$idClasse), &$clsSing, FALSE, 'reflection', TRUE);

		if(method_exists(&$nameSpace, '__construct') || $totalParams) {

			if($totalParams) {

				$arrayParams =& self::$_arrayParams;

				try {

					$arrayParamsReflection =& $init->getMethod('__construct')->getParameters();

					if(!count(&$arrayParamsReflection)) {

						throw \Core\Uses\Exception('Construtor não possui parametros ou não existe.');
					}

					$arrayNewParams = array();

					foreach($arrayParamsReflection as $i => $param) {

						if($param->isPassedByReference()) {

							$arrayNewParams[$i] =& $arrayParams[$i];
						}

						else {

							$arrayNewParams[$i] = $arrayParams[$i];
						}
					}
				}

				catch(\Exception $e) {

					throw \Core\Uses\Exception('Construtor nao possui parametros ou nao existe.');
				}

				$reflection =& self::loadInstance(array(&$nameSpace, &$idClasse), &$clsSing, self::$resetProperties, TRUE, FALSE, array(&$arrayNewParams));
				unset($init, $arrayParamsReflection, $arrayNewParams);
				self::$_classSingleton = self::$_arrayParams = NULL;
				self::$resetProperties = TRUE;
				return $reflection;
			}

			else {

				$reflection =& self::loadInstance(array(&$nameSpace, &$idClasse), &$clsSing, self::$resetProperties, TRUE, FALSE, TRUE);
				unset($init);
				self::$_classSingleton = NULL;
				self::$resetProperties = TRUE;
				return $reflection;
			}
		}

		else {

			$reflection =& self::loadInstance(array(&$nameSpace, &$idClasse), &$clsSing, self::$resetProperties, TRUE, FALSE);
			unset($init);
			self::$_classSingleton = NULL;
			self::$resetProperties = TRUE;
			return $reflection;
		}
	}
}
?>